/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2022-12-05     yoyoyes      first version
 */

#include "thread_mutex_demo2.h"

static rt_thread_t tid1 = RT_NULL;
static rt_thread_t tid2 = RT_NULL;
static rt_thread_t tid3 = RT_NULL;
static rt_mutex_t mutex = RT_NULL;

/*
 * @brief  线程1入口函数，检查thread2和thread3优先级情况
 *
 * @param  parameter 线程1入口函数参数
 *
 * @return None
 */
static void rt_thread1_entry(void *parameter)
{
    rt_thread_mdelay(100);              /* 先让低优先级线程运行 */

    if(tid2->current_priority != tid3->current_priority)
    {
        /* 优先级不同，测试失败 */
        rt_kprintf("thread1 print:the priority of thread2 is %d\n", tid2->current_priority);
        rt_kprintf("thread1 print:the priority of thread3 is %d\n", tid3->current_priority);
        rt_kprintf("thread1 print:test failed.\n");

        return;
    }
    else
    {
        rt_kprintf("thread1 print:the priority of thread2 is %d\n", tid2->current_priority);
        rt_kprintf("thread1 print:the priority of thread3 is %d\n", tid3->current_priority);
        rt_kprintf("thread1 print:test OK.\n");
    }
}

/*
 * @brief  线程2入口函数，试图持有互斥锁，此时 thread3 持有，应把 thread3 的优先级提升到 thread2 相同的优先级
 *
 * @param  parameter 线程2入口函数参数
 *
 * @return None
 */
static void rt_thread2_entry(void *parameter)
{
    rt_err_t result;

    rt_kprintf("thread2 print:the priority of thread2 is %d\n", tid2->current_priority);

    rt_thread_mdelay(50);               /* 先让低优先级线程运行 */

    result = rt_mutex_take(mutex, RT_WAITING_FOREVER);
    if(result == RT_NULL)
        rt_mutex_release(mutex);
}

/*
 * @brief  线程3入口函数，线程3先持有互斥量，而后线程2试图持有互斥量，此时线程3的优先级被提升为和线程2的优先级相同
 *
 * @param  parameter 线程3入口函数参数
 *
 * @return None
 */
static void rt_thread3_entry(void *parameter)
{
    rt_tick_t tick;
    rt_err_t result;

    rt_kprintf("thread3 print:the priority of thread3 is %d\n", tid3->current_priority);

    result = rt_mutex_take(mutex, RT_WAITING_FOREVER);
    if(result != RT_NULL)
        rt_kprintf("thread3 print:thread3 take a mutex failed.\n");

    /* 做一个长时间的循环，500ms */
    tick = rt_tick_get();
    while(rt_tick_get() - tick < (RT_TICK_PER_SECOND) / 2);

    rt_mutex_release(mutex);
}

/*
 * @brief  互斥量Demo2函数，检查持有互斥量时，持有的线程优先级是否被调整到等待线程优先级中的最高优先级
 *
 * @param  None
 *
 * @return None
 */
int thread_mutex_demo2(void)
{
    /* 创建互斥锁 */
    mutex = rt_mutex_create("mutex", RT_IPC_FLAG_PRIO);
    if(mutex == RT_NULL)
    {
        rt_kprintf("create dynamic mutex failed.\n");
        return -1;
    }

    /* 创建线程1 */
    tid1 = rt_thread_create("thread1", rt_thread1_entry, RT_NULL, THREAD_STACK_SIZE, THREAD_PRIORITY - 1, THREAD_TIMESLICE);
    if(tid1 != RT_NULL)
        rt_thread_startup(tid1);

    /* 创建线程2 */
    tid2 = rt_thread_create("thread2", rt_thread2_entry, RT_NULL, THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE);
    if(tid2 != RT_NULL)
        rt_thread_startup(tid2);

    /* 创建线程3 */
    tid3 = rt_thread_create("thread3", rt_thread3_entry, RT_NULL, THREAD_STACK_SIZE, THREAD_PRIORITY + 1, THREAD_TIMESLICE);
    if(tid3 != RT_NULL)
        rt_thread_startup(tid3);

    return 0;
}
